


#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <malloc.h>
#include <cstring>




// #define DEBUG_MEMORY

#ifdef DEBUG_MEMORY
const int MEG= 1 << 20;
const int poolsz = 20 * MEG;
const int poolidxsz = MEG;

static char *my_pool;
static char *pool_end;

class SegmentDescription
{
public:
	char *segment_ptr;
	char freed;
	size_t size;

	// store origin?
};

class SegmentDescription * segments;

static int segment_array_idx;


int FindSegmentIDX (char *p)
{
	int lo = 0;
	int hi = segment_array_idx;
	int cmp;
	/* binary search */
	do
	{
		cmp = (lo + hi) / 2;

		int result = p - segments[cmp].segment_ptr;

		if (result < 0)
			hi = cmp;
		else
			lo = cmp;
	}
	while (hi - lo > 1);
	return lo;
}

void * MyMalloc(size_t s, void const  * caller)
{
	if (!s)			// we want unique adresses. 
		s ++;
	char * p = segments[segment_array_idx].segment_ptr;
	char *ep = p + s;

	assert (ep < pool_end);

	char *scramble = p;
	while (scramble < ep)
	{
		*scramble++ = 0x55;
	}

	segments[segment_array_idx].freed = 0;
	segments[segment_array_idx].size = s;
	segment_array_idx++;
	assert (segment_array_idx < poolidxsz);


	segments[segment_array_idx].segment_ptr = ep;
	return p;
}


void * MyRealloc (void * ptr, size_t sz, const void * caller)
{
	void  * newblock =   MyMalloc (sz, caller);

	if (ptr)
	{
		char * cp = (char*)ptr;
		int idx = FindSegmentIDX (cp);

		assert (segments[idx].segment_ptr == cp);
		assert (!segments[idx].freed);

		memcpy (newblock, cp, segments[idx].size  <? sz);
		segments[idx].freed = 1;
	}  
	return newblock;
}

void MyFree (void *vp, void const  * caller)
{
	if (vp == 0)
		return;

	char * p = (char*)vp;
	int idx = FindSegmentIDX (p);


	assert (segments[idx].segment_ptr == p);
	assert (!segments[idx].freed);

	segments[idx].freed = 1;

	char * cp = (char*)p;
	char * ep = segments[idx + 1].segment_ptr;

	while (cp < ep)
	{
		*cp  = 0x66;
		cp ++;
	}
}



void InitMyAllocators ()
{

	my_pool = (char*)malloc (poolsz);
	pool_end = my_pool + poolsz;

	segments = (SegmentDescription*) malloc (poolidxsz  * sizeof (SegmentDescription) );

	segments[0].segment_ptr = my_pool;
	segments[0].freed = 0;

	__malloc_hook = &my_malloc;
	__free_hook = &my_free ;
	__realloc_hook = &my_realloc;  

}
#else
void InitMyAllocators () {}
#endif
